ANDROID: 16K: Don't set padding vm_flags on 32-bit archs

vma_pad_fixup_flags() and is_mergable_pad_vma() were inadvertently
affecting the vm_flags on 32-bit arch, making some VMAs not mergable.

This causes zygote to crash as the Art GC's heap compaction fails.

The compaction depends on mremap() which will fail when operating on
a range that spans multiple VMAs [1]. This can happen now due to the
incorrect is_mergable_pad_vma() check.

Make all the pgsize_migration APIs no-ops in 32-bit architectures,
since Android only performs ELF segment extension in 64-bit archs.

[1] https://github.com/torvalds/linux/blob/v6.9/mm/mremap.c#L841-L843

Bug: 353667356
Change-Id: Id9b0076ef173d75a4afc85577355d340fce03e65
Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
diff --git a/include/linux/pgsize_migration.h b/include/linux/pgsize_migration.h
index fbfb1b9..e3dc1de 100644
--- a/include/linux/pgsize_migration.h
+++ b/include/linux/pgsize_migration.h
@@ -62,6 +62,14 @@ extern void show_map_pad_vma(struct vm_area_struct *vma,
 
 extern void split_pad_vma(struct vm_area_struct *vma, struct vm_area_struct *new,
 			  unsigned long addr, int new_below);
+
+extern unsigned long vma_pad_fixup_flags(struct vm_area_struct *vma,
+					 unsigned long newflags);
+
+extern bool is_mergable_pad_vma(struct vm_area_struct *vma,
+				unsigned long vm_flags);
+
+extern unsigned long vma_data_pages(struct vm_area_struct *vma);
 #else /* PAGE_SIZE != SZ_4K || !defined(CONFIG_64BIT) */
 static inline void vma_set_pad_pages(struct vm_area_struct *vma,
 				     unsigned long nr_pages)
@@ -98,36 +106,22 @@ static inline void split_pad_vma(struct vm_area_struct *vma, struct vm_area_stru
 				 unsigned long addr, int new_below)
 {
 }
-#endif /* PAGE_SIZE == SZ_4K && defined(CONFIG_64BIT) */
 
-static inline unsigned long vma_data_pages(struct vm_area_struct *vma)
-{
-	return vma_pages(vma) - vma_pad_pages(vma);
-}
-
-/*
- * Sets the correct padding bits / flags for a VMA split.
- */
 static inline unsigned long vma_pad_fixup_flags(struct vm_area_struct *vma,
 						unsigned long newflags)
 {
-	if (newflags & VM_PAD_MASK)
-		return (newflags & ~VM_PAD_MASK) | (vma->vm_flags & VM_PAD_MASK);
-	else
-		return newflags;
+	return newflags;
 }
 
-/*
- * Merging of padding VMAs is uncommon, as padding is only allowed
- * from the linker context.
- *
- * To simplify the semantics, adjacent VMAs with padding are not
- * allowed to merge.
- */
 static inline bool is_mergable_pad_vma(struct vm_area_struct *vma,
 				       unsigned long vm_flags)
 {
-	/* Padding VMAs cannot be merged with other padding or real VMAs */
-	return !((vma->vm_flags | vm_flags) & VM_PAD_MASK);
+	return true;
 }
+
+static inline unsigned long vma_data_pages(struct vm_area_struct *vma)
+{
+	return vma_pages(vma);
+}
+#endif /* PAGE_SIZE == SZ_4K && defined(CONFIG_64BIT) */
 #endif /* _LINUX_PAGE_SIZE_MIGRATION_H */
diff --git a/mm/pgsize_migration.c b/mm/pgsize_migration.c
index bca3c4a..3b89b64 100644
--- a/mm/pgsize_migration.c
+++ b/mm/pgsize_migration.c
@@ -421,5 +421,37 @@ void split_pad_vma(struct vm_area_struct *vma, struct vm_area_struct *new,
 		vma_set_pad_pages(second, nr_vma2_pages);
 	}
 }
+
+/*
+ * Sets the correct padding bits / flags for a VMA split.
+ */
+unsigned long vma_pad_fixup_flags(struct vm_area_struct *vma,
+				  unsigned long newflags)
+{
+	if (newflags & VM_PAD_MASK)
+		return (newflags & ~VM_PAD_MASK) | (vma->vm_flags & VM_PAD_MASK);
+	else
+		return newflags;
+}
+
+/*
+ * Merging of padding VMAs is uncommon, as padding is only allowed
+ * from the linker context.
+ *
+ * To simplify the semantics, adjacent VMAs with padding are not
+ * allowed to merge.
+ */
+bool is_mergable_pad_vma(struct vm_area_struct *vma,
+			 unsigned long vm_flags)
+{
+	/* Padding VMAs cannot be merged with other padding or real VMAs */
+	return !((vma->vm_flags | vm_flags) & VM_PAD_MASK);
+}
+
+unsigned long vma_data_pages(struct vm_area_struct *vma)
+{
+	return vma_pages(vma) - vma_pad_pages(vma);
+}
+
 #endif /* PAGE_SIZE == SZ_4K */
 #endif /* CONFIG_64BIT */